package com.JAVA的形参和实参;

import java.lang.reflect.Field;

public class WrongMain {

	public static void main(String[] args) {
		Integer a = 1;
		Integer b = 2;
		System.out.println("a=" + a + ",b=" + b);
		swap4(a, b);
		System.out.println("a=" + a + ",b=" + b);
	}

	//希望交换a、b的值输出，但实际输出
	//a=1,b=2
	//numa=2,numb=1
	//a=1,b=2
	private static void swap(Integer numa, Integer numb) {
		Integer tmp = numa;
		numa = numb;
		numb = tmp;
		System.out.println("numa=" + numa + ",numb=" + numb);
	}
	
	//a=1,b=2
	//a=2,b=2
	private static void swap2(Integer numa, Integer numb) {
		Integer tmp = numa;
		try {
			Field field = Integer.class.getDeclaredField("value");
			field.setAccessible(true);
			field.set(numa, numb); // 成功的将numa 引用的 1的对象 值改为 2
			field.set(numb, tmp); // 由于 tmp 也是指向 numa，未改变前指向的堆 即对象1 ，经过前一步，已经将对象1的值改为了2，自然 numb也是2
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	//a=1,b=2
	//a=2,b=2
	//将a、b分别改为129、130，就可以正常修改，那是因为：
	//java推荐 Integer.valueOf 方式初始化一个 Interger因为有 缓存了 -128-127的数字 我们直接定义 Integera=1 具有这个功能，所以 Jvm 底层实现 是通过 Integer.valueOf这个方法
	//再看 field.set(numb,tmp); 我们打断点，发现通过反射设置 value时 竟然走了 Integer.valueOf 方法 
	private static void swap3(Integer numa, Integer numb) {
		int tmp = numa.intValue();// tmp 定义为基本数据类型
		try {
			//在反射修改前
			//IntegerCache.cache[128]=0
			//IntegerCache.cache[129]=1
			//IntegerCache.cache[130]=2
			Field field = Integer.class.getDeclaredField("value");
			field.setAccessible(true);
			//通过反射修改后
			//IntegerCache.cache[128]=0
			//IntegerCache.cache[129]=2
			//IntegerCache.cache[130]=2
			field.set(numa, numb); //这个时候并不改变 tmp 的值
			field.set(numb, tmp);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	private static void swap4(Integer numa, Integer numb) {
		int tmp = numa.intValue();// tmp 定义为基本数据类型
		try {
			Field field = Integer.class.getDeclaredField("value");
			field.setAccessible(true);
			field.set(numa, numb); //这个时候并不改变 tmp 的值
			field.set(numb, new Integer(tmp));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}
